import * as ol from '../openLayer'
import { defaultConfig, coordinatesTypeArr } from './config'
import { click, pointerMove } from 'ol/events/condition.js'
// import { deepAssign,deepCopyData } from '@/utils'
import { deepAssign ,deepCopyData} from '@/utils/tools/index.js'
import { LineString,Circle ,Point} from 'ol/geom'
import {Circle as StyleCircle} from 'ol/style';
import * as turf from '@turf/turf'
import {Style} from 'ol/style.js';
import { WKT, GeoJSON, TopoJSON } from 'ol/format'
import {getRadius} from '../../handle'

/**
 * 轨迹类（多线条）
 */
export default class OlMapTrajectorys {
  constructor (_map, _config) {
    // console.log('_mapg',_map)
    // console.log('_config',_config)
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
    this.status = _config.status
    this.route = _config.route
    this.coordinatesType = coordinatesTypeArr.indexOf(this.options.coordinatesType) > -1 ? this.options.coordinatesType : defaultConfig.coordinatesType
    this.cacheCoordinates = deepCopyData(this.options.coordinates)//  点位信息
    this.coordinates = [] // 坐标点
    this.routeFeatures = [] // 线路features
    this.routeLines = []// 线路string
    this.intersectPoints = [] // 线路相交点位
    this.overlayPopupElement = null // 提示框
    this.overlayPopup = null
    this.topoindex = null
    this.item = []
    this.lineStyle = null
    this.styles = []
    this.prevCoord = []
    this.currCoord = []
    this.rotation = '' // 注意方向调整
    this.arrows =[]
    if (this.options.coordinates.length > 0) {
      this.arrayObjectToArray(_config.status )
    }
  }
  /**
   * 提取coordinates和每条线路的样式
   */
  arrayObjectToArray (){
    let lineStyleArr = []
    let startPointStyleArr=[]
    let endPointStyleArr = []
    let stopPointStyleArr = []
    let multPointsArr = []

    let cachePointsArr = [] // 点位缓存，为了过滤掉points 不纯在的情况
    for (let i of this.cacheCoordinates) {
      let pointsArr = []
      let pointsAttrArr= [] // 点位带属性
      lineStyleArr.push(i?.lineStyle||null)
      startPointStyleArr.push(i?.startPointStyle||null)
      endPointStyleArr.push(i?.endPointStyle||null)
      stopPointStyleArr.push(i?.stopPointStyle||null)
      if(i?.points){
        if(i.points.length>0){
          pointsAttrArr.push(...i.points)
          for(let item of i.points){
            if(item?.point){
              let newItemPoints = []
              switch (this.coordinatesType) {
                case 'WKT':
                  newItemPoints = new WKT().readGeometry(item.point).getCoordinates()
                  break
                case 'point':
                  newItemPoints = item?.point
                  break
                default:
                  newItemPoints = new WKT().readGeometry(item.point).getCoordinates()
                  break
              }
              pointsArr.push(newItemPoints)
            }
          }
        }else{
          pointsAttrArr.push([])
        }
      }else{
        pointsAttrArr.push([])
      }
      multPointsArr.push(pointsArr)
      this.arrows = multPointsArr[0]
      cachePointsArr.push({
        lineStyle:(i?.lineStyle&&JSON.stringify(i.lineStyle)!=='{}')?i.lineStyle:null,
        startPointStyle:(i?.startPointStyle&&JSON.stringify(i.startPointStyle)!=='{}')?i.startPointStyle:null,
        endPointStyle: (i?.endPointStyle&&JSON.stringify(i.endPointStyle)!=='{}')?i.endPointStyle:null,
        stopPointStyle: ( i?.stopPointStyle&&JSON.stringify(i.stopPointStyle)!=='{}')?i.stopPointStyle:null,
        points:pointsAttrArr
      })
    }
    lineStyleArr = this.initStyleArr(lineStyleArr,'lineStyleArr')
    startPointStyleArr = this.initStyleArr(startPointStyleArr,'startPointStyleArr')
    endPointStyleArr= this.initStyleArr(endPointStyleArr,'endPointStyleArr')
    stopPointStyleArr= this.initStyleArr(stopPointStyleArr,'stopPointStyleArr')
    let config = {
      actions:this.options.actions,
      intersectConfig:this.options.intersectConfig,
      lineStyleArr,
      startPointStyleArr,
      endPointStyleArr,
      stopPointStyleArr,
      coordinates:multPointsArr
    }
    this.options = deepAssign(defaultConfig, config) //  配置项
    this.cacheCoordinates = deepCopyData(cachePointsArr) 
    this.drawRoutes()
  }
  initStyleArr(arr=[],key){
    let newArr = arr.filter(item=>item!==null)
    if (newArr.length > 0) {
      let length = defaultConfig[key].length
      if (newArr.length > defaultConfig[key].length ) { 
        newArr = newArr.map((item, index) => {
          if (JSON.stringify(newArr[index]) !== '{}'&& newArr[index] ) {
            item = newArr[index]
          }else{
            item = defaultConfig[key][index%length]
          }
          return item
        })
        return newArr
      } else {// 相等 或者小于defaultConfig[key].length
        newArr = defaultConfig[key].map((item, index) => {
          if (JSON.stringify(newArr[index]) !== '{}'&& newArr[index] ) {
            item = newArr[index]
          } 
          return item
        })
        return newArr
      }
    }else{
      return this.options[key]
    }
  }
  /**
   * 绘制线路
   */
  drawRoutes(){
    this.options.coordinates.forEach((item,index)=>{
      this.styles = []
      this.item = item
      if(this.route == 'topology'){
        this.lineStyle = {
          color: "#54a5f0",
          width: 2
        }
      }else{
        let lineStyle  = this.getCurrentPointStyle(index,'lineStyle')
        this.lineStyle = lineStyle
      }
      let lineString = new LineString(item)
      this.routeLines.push(turf.lineString(item))
      let lineFeatures =  new ol.Feature({ //  直线线路
        'type':'line',
        geometry: lineString,
        properties: this.cacheCoordinates[index],
        style: this.lineStyle,
        vectorLayer:this.options.layerProperties?.id||'TrajectoryLayers'
      })
      // 添加线段样式--tracert页面的线需要加粗显示，其他页面不需要，添加判断
      this.styles.push(
        new Style({
          stroke: new ol.Stroke({
            color: this.lineStyle.color,
            width: this.route == 'tracert' ? this.lineStyle.width *2.5 : this.lineStyle.width
          })
        })
      )
      // 添加箭头样式---只有Ip定位不需要--需要添加判断
      if(this.route == 'tracert'){
        for (let i = 0; i < this.item.length-1; i++) {
          this.prevCoord = this.item[i]
          this.currCoord = this.item[i+1]
          let newlng = (this.prevCoord[0]+this.currCoord[0])/2
          let newlat = (this.prevCoord[1]+this.currCoord[1])/2
          let newCenter = [newlng,newlat]
          const directionVector = [
            this.prevCoord[1] - this.currCoord[1],
            this.prevCoord[0] - this.currCoord[0],
          ];
          const rotationAngleRadians = Math.atan2(directionVector[0], directionVector[1]);
          this.rotation = -rotationAngleRadians; // 注意方向调整
          const arrowStyleRotated = new Style({
            image: new ol.Icon({
              anchor: [0.45, 0.5], // 假设箭头的尖端在底部中心，根据图标实际调整
              anchorXUnits: 'fraction',
              anchorYUnits: 'fraction',
              src: require("@/assets/images/arrow4.png"),
              rotateWithView: false,
              scale: 0.25,
              rotation: this.rotation, // 直接在这里设置旋转角度
            }),
            geometry: () => new ol.Point(newCenter), // 设置箭头的位置
          }) 
          this.styles.push(arrowStyleRotated)
        }
      }
      lineFeatures.setStyle(this.styles)
      this.lineFeatures = lineFeatures
      let startPointStyle = this.getCurrentPointStyle(index,'startPointStyle')
      let startFeature = new ol.Feature({
        type: 'point',
        subType:'startPoint',
        geometry: new Point(item[0]),
        properties: this.cacheCoordinates[index]['points'][0],
        style:startPointStyle,
        vectorLayer:this.options.layerProperties?.id||'TrajectoryLayers',
        tracertStatus:this.status
      })
      let endPointStyle = this.getCurrentPointStyle(index,'endPointStyle')
      let endFeature = new ol.Feature({
        type: 'point',
        subType:'endPoint',
        geometry:  new Point(item[item.length-1]),
        properties: this.cacheCoordinates[index]['points'][item.length-1],
        style:endPointStyle,
        vectorLayer:this.options.layerProperties?.id||'TrajectoryLayers',
        tracertStatus:this.status
      })
      let stopPointStyle= this.getCurrentPointStyle(index,'stopPointStyle')
      let stopFeatureArr =[]
      item.forEach((citem,cindex)=>{
       if(cindex!==0&&cindex!==item.length-1){
        let stopFeature=new ol.Feature({
          type:'point',
          subType:'stopPoint',
          geometry:  new Point(citem),
          properties: this.cacheCoordinates[index]['points'][cindex],
          style:stopPointStyle,
          vectorLayer:this.options.layerProperties?.id||'TrajectoryLayers'
        })
        stopFeature.setStyle(
          new Style({
            image: new StyleCircle({
              radius: stopPointStyle.radius,
              fill: new ol.Fill({
                color:stopPointStyle.fillColor,
              })
            })
          })
        )
        stopFeatureArr.push(stopFeature) 
       } 
      })
      if(this.route == 'tracert' && this.status == 'COMPLETED'){ //路由路径页面-探测成功，有终点
        startFeature.setStyle(
          new Style({
            image: new ol.Icon({
              src:  require("@/assets/images/map/marker-icon/start5.png"),
              anchor: [0.52, 0.96],
              scale: 0.45
            })
          })
        )
        endFeature.setStyle(new Style({
          image: new ol.Icon({
            src:  require("@/assets/images/map/marker-icon/end3.png"),
            anchor: [0.45, 0.90],
            scale: 0.35
          })
        }))
      }else if(this.route == 'tracert' && this.status == 'UNREACH'){//路由路径页面-探测失败，只有起点，无终点
        startFeature.setStyle(
          new Style({
            image: new ol.Icon({
             src:  require("@/assets/images/map/marker-icon/start5.png"),
              anchor: [0.55, 0.85],
              scale: 0.45
            })
          })
        )
        endFeature.setStyle(
          new Style({
            image: new StyleCircle({
              radius: stopPointStyle.radius,
              fill: new ol.Fill({
                color:stopPointStyle.fillColor,
              })
            })
          })
        )
      }else if(this.route == 'location'){
        //IP定位界面，起点和终点的图标用红色和蓝色表示
        startFeature.setStyle(
          new Style({
            image: new ol.Icon({
              src:  require("@/assets/images/map/marker-icon/markerRed.png"),
             anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        )
        endFeature.setStyle(new Style({
          image: new ol.Icon({
            src:  require("@/assets/images/map/marker-icon/markerBlue.png"),
            anchor: [0.5, 0.9],
            scale: 0.5
          })
        }))
      }else if(this.route == 'topology'){
        //网络拓扑界面，起点和终点都用圆点表示
        startFeature.setStyle(
          new Style({
            image: new ol.Icon({
              src:  require("@/assets/images/map/marker-icon/circle1.png"),
             anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        )
        endFeature.setStyle(new Style({
          image: new ol.Icon({
            src:  require("@/assets/images/map/marker-icon/circle1.png"),
            anchor: [0.5, 0.9],
            scale: 0.5
          })
        }))
      }
      this.routeFeatures.push(lineFeatures,startFeature,endFeature,...stopFeatureArr)
    })
    if (this.options.intersectConfig?.open) {// 计算相交点
      let intersectFeatures = this.initIntersectPoints()
      if(intersectFeatures.length>0){ // 有相交点
        this.routeFeatures.push(...intersectFeatures)
      }
    }
    this.trajectoryLayer = new ol.VectorLayer({ // 添加图层
      source: new ol.VectorSource({
        features: this.routeFeatures,
      }),
      className: 'TrajectoryLayers',
      properties: this.options.layerProperties
    })
    var lineStringGeometry = new LineString(this.arrows);
    var routeFeature = new ol.Feature({
      geometry: lineStringGeometry,
    });
    this.map.addLayer(this.trajectoryLayer)
    this.attachActionListener()  
  }
  /**
   * 计算相交点位
   */
  initIntersectPoints(){
    this.intersectPoints = []
    let intersectConfig = this.options.intersectConfig
    switch(intersectConfig.dataSource){
      case 'web':
        for(let i=0;i<this.routeLines.length;i++){
          for(let j=i+1;j<this.routeLines.length;j++){
            let point = turf.lineIntersect(this.routeLines[i],this.routeLines[j])
            // console.log('this.intersectPoints=',point,point.features)
            if(point.features.length>0){
              this.intersectPoints.push(...point.features)
            }
          }
        }
        break;
      case 'server':
    
        this.intersectPoints = deepAssign(intersectConfig.intersectPoints)
        break;
      default: // 默认服务端计算
      this.intersectPoints = deepAssign(intersectConfig.intersectPoints)
        break
    }

    if (this.intersectPoints.length > 0) {
    
    
      return this.drawIntersectPoints()
      }else{
        return []
      }
  }
  /**
   * 绘制相交点
   */
  drawIntersectPoints(){
    let intersecFeatures =  []
    let intersectConfig = this.options.intersectConfig
    let type = 'server'
    let intersecPoints = []
    switch(intersectConfig.dataSource){
      case 'web':
        type = 'web'
      break;
      case 'server':
        type = 'server'
        break;
      default: // 默认服务端计算
      type = 'server'
        break
    }
   
    this.intersectPoints.forEach(item => {
     
      let feature 
      if(type==='server'){
        feature= new ol.Feature({
          geometry:  new WKT().readGeometry(item.point),
        })
      }else{
        feature= new GeoJSON().readFeature(item)
      }
      
      feature.setProperties({
        type:'point',
        subType:'intersectPoint',
        vectorLayer:this.options.layerProperties?.id||'TrajectoryLayers',
        style:this.options.intersectConfig.pointStyle,
        properties: {
          points:type==='server'?item:new GeoJSON().readGeometry(item.geometry).getCoordinates()
        }
      })
      feature.setStyle(new Style({
        image: new StyleCircle({
          radius: this.options.intersectConfig.pointStyle.radius,
          fill: new ol.Fill({
            color:this.options.intersectConfig.pointStyle.fillColor,
          }),
          stroke: new ol.Stroke({
            color: this.options.intersectConfig.pointStyle.strokeColor,
            width:this.options.intersectConfig.pointStyle.strokeWidth
          })
        })
      }))
      // 设置大圆圈
      let center =feature.getGeometry().getCoordinates()
      let style = this.options.intersectConfig.circleStyle
      let radius = getRadius(this.map,style.radius)
      let circleFeature = new ol.Feature({
        geometry:new Circle(center,radius)
      })
      circleFeature.setStyle(
        new Style({
          fill:  new ol.Fill({
            color: style.fillColor,
          }),
          stroke: new ol.Stroke({
            color: style.strokeColor
          })
        }),
      );
      intersecFeatures.push(...[feature,circleFeature])
      intersecPoints.push(feature.get('properties'))
    })

    if(intersectConfig?.callback){
      intersectConfig.callback(intersecPoints)
    }
    return intersecFeatures
  }
  /**
   * 添加监听
   */
  attachActionListener () {
    if (this.options.actions.length > 0) {
      for (const action of this.options.actions) { //  绑定事件
        const condition = action.type === 'hover' ? pointerMove : click // 默认有点击事件
        const eventType = action.eventType
        const trajectoryEvents = new ol.Select({
          style: (feature) => this.setSelectStyle(feature), // 设置选中的样式
          condition: condition,
          hitTolerance: action.hitTolerance || 5, // 命中容差默认是5
          filter:(feature)=>{
            return feature.get('vectorLayer')
          }
        })
        this.map.addInteraction(trajectoryEvents)
        trajectoryEvents.on('select', (e) => {
          const selectedfeatureArr = e.selected
          const length = selectedfeatureArr.length
          let type = length?selectedfeatureArr[0].get('type'):null
          let subType= length?selectedfeatureArr[0].get('subType'):null
          if (length>0&&type===eventType) { //  有数据值
            let propertiesList = selectedfeatureArr.map(item=> item.get('properties'))
            action.handle(propertiesList)
          }
        })
      }
    }
  }
  /**
   * 设置选中的样式
   */
  setSelectStyle(feature) {
    let type = feature.get('type')
    let lineStyle = feature.get('style')
    if(type==='line'){
      if(this.route == 'tracert'){
        return new Style({
          stroke:  new ol.Stroke({
            width: lineStyle.width*2.8,
            color: lineStyle.color
          })
        })
      }else{
        return new Style({
          stroke:  new ol.Stroke({
            width: lineStyle.width,
            color: lineStyle.color
          })
        })
      }     
    }else{
      let subType = feature.get('subType')
      let pointStyle = feature.get('style')
      let status = feature.get('tracertStatus') //通过feature传status值，否则读取的不是当下的状态
      if (subType && subType === 'stopPoint') { // 途径点
        return new Style({
          image: new StyleCircle({
            radius: pointStyle.radius, //统一和mark保持一致，不加放大的效果,如需加修改成pointStyle.radius*2
            fill: new ol.Fill({
              color: pointStyle.fillColor,
            })
          })
        })
      } else if (subType && subType === 'startPoint') {
        if(this.route == 'tracert' && status == 'COMPLETED'){  
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/start5.png"),
              anchor: [0.52, 0.96],
              scale: 0.45 //统一和mark保持一致，不加放大的效果,如需加修改成0.8，下面同
            })
          })
        }else if(this.route == 'tracert' && status == 'UNREACH'){  
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/start5.png"),
              anchor: [0.55, 0.85],
              scale: 0.45 //统一和mark保持一致，不加放大的效果,如需加修改成0.8，下面同
            })
          })
        }else if(this.route == 'location'){
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/markerRed.png"),
              anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        }else if(this.route == 'topology'){
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/circle1.png"),
              anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        }
      } else if (subType && subType === 'endPoint') { 
        if(this.route == 'tracert' && status == 'COMPLETED'){ //路由路径页面-探测成功，有终点
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/end3.png"),
              anchor: [0.45, 0.90],
              scale: 0.35
            })
          })
        }else if(this.route == 'tracert' && status == 'UNREACH'){//路由路径页面-探测失败，无终点
          return new Style({
            image: new StyleCircle({
              radius: pointStyle.radius*1.5,
              fill: new ol.Fill({
                color: pointStyle.fillColor,
              })
            })
          })
        }else if(this.route == 'location'){//IP定位页面
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/markerBlue.png"),
              anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        }else if(this.route == 'topology'){//网络拓扑页面
          return new Style({
            image: new ol.Icon({
              src: require("@/assets/images/map/marker-icon/circle1.png"),
              anchor: [0.5, 0.9],
              scale: 0.5
            })
          })
        }
      } else{//相交点 --此项目中无相交点
        return new Style({
          image: new StyleCircle({
            radius: pointStyle.radius*1.5,
            fill: new ol.Fill({
              color:pointStyle.fillColor,
            }),
            stroke: new ol.Stroke({
              color: pointStyle.strokeColor,
              width:pointStyle.strokeWidth*1.2
            })
          }),
        })
      }
    }
    
  }
  /**
   * 获取样式
   * @param {*} index 当前下标
   * @param {*} key 
   * @returns 
   */
  getCurrentPointStyle (index,key){
    let style = null
    if(this.cacheCoordinates[index][key]){
      style = this.cacheCoordinates[index][key]
    }else if(this.options[`${key}Arr`].length>0){
      let length = this.options[`${key}Arr`].length
      let newIndex = index%length
      style = this.options[`${key}Arr`][newIndex]
    }else{
      style = this.options[key]
    }
    return style
  }
  
  updateTrajectory (_map, _config) {
    this.map = _map
    this.options = deepAssign(defaultConfig, _config) //  配置项
  }
}
